﻿using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using StockUtil;

namespace StockLib.UserData.DZH
{
    public class BlockRegularFileLoader : StockLib.UserData.BlockRegularFileLoader
    {
        private string GetBlockDir()
        {
            // HKEY_LOCAL_MACHINE\SOFTWARE\dzh\SuperStk  InstPath
            string installDir = string.Empty;
            RegistryKey registryKey = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\dzh\SuperStk");
            if (registryKey != null)
            {
                installDir = Convert.ToString(registryKey.GetValue("InstPath"));
            }
            if (string.IsNullOrEmpty(installDir))
            {
                installDir = @"D:\Program Files\大智慧2";
            }

            string blockDir = installDir + @"\userdata\block\";
            return blockDir;
        }

        private string GetBlockDirFile(string fileName)
        {
            return GetBlockDir() + fileName;
        }

        private string GetBlockDefFile()
        {
            return GetBlockDirFile(@"BLOCK.DEF");
        }

        private string GetBlockDomainFile(string domainName)
        {
            return GetBlockDirFile(domainName + ".BLK");
        }

        public override void Load()
        {
            FileInfo fi = new FileInfo(GetBlockDefFile());
            if (!fi.Exists)
                return;

            FileStream fs = null;
            StreamReader sr = null;

            try
            {
                fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                sr = new StreamReader(fs, System.Text.Encoding.Default);

                StockBlockGroupRegular.Instance.Clear();

                string className = string.Empty;
                while (!sr.EndOfStream)
                {
                    string line = sr.ReadLine();
                    if (!string.IsNullOrEmpty(line))
                        line = line.Trim();
                    if (string.IsNullOrEmpty(line))
                        continue;

                    Match match = Regex.Match(line, @"\[(.+)\]");
                    if (match.Success)
                    {
                        className = ConvertDomainClass(match.Groups[1].Value);
                        continue;
                    }

                    if (string.IsNullOrEmpty(className))
                    {
                        continue;
                    }

                    StockBlock domain = new StockBlock();
                    domain.Name = line;
                    domain.ShortName = StringHelper.GetPinYin(domain.Name);
                    domain.GroupName = className;
                    if (!StockBlockGroupRegular.Instance.ContainsKey(domain.BlockId))
                    {
                        StockBlockGroupRegular.Instance.Add(domain.BlockId, domain);
                        LoadDomain(domain);
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw ex;
            }
            finally
            {
                if (sr != null)
                {
                    sr.Close();
                    sr.Dispose();
                }
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                }
            }
        }

        private void LoadDomain(StockBlock domain)
        {
            FileInfo fi = new FileInfo(GetBlockDomainFile(domain.Name));
            if (!fi.Exists)
                return;

            FileStream fs = null;
            try
            {
                fs = new FileStream(fi.FullName, FileMode.Open, FileAccess.Read, FileShare.Read);
                fs.Seek(Marshal.SizeOf(typeof(DomainFileHead)), SeekOrigin.Begin);
                byte[] buffer = new byte[Marshal.SizeOf(typeof(DomainFilePack))];
                while (fs.Read(buffer, 0, buffer.Length) > 0)
                {
                    DomainFilePack pack = (DomainFilePack)StructHelper.FromBytes(buffer, typeof(DomainFilePack));
                    string codeKey = GetCodeKey(ref pack);
                    if (StockContainer.Instance.ContainsKey(codeKey) && !domain.ContainsKey(codeKey))
                    {
                        domain.Add(codeKey, StockContainer.Instance[codeKey]);
                    }
                }
                domain.StockNumber = domain.Count;
            }
            catch (Exception ex)
            {
                Trace.WriteLine(ex.ToString());
                throw ex;
            }
            finally
            {
                if (fs != null)
                {
                    fs.Close();
                    fs.Dispose();
                }
            }
        }

        private string GetCodeKey(ref DomainFilePack pack)
        {
            return ConvertMarketToInternal(pack.m_wMarket).ToString().ToUpper() + pack.m_szLabel;
        }

        private StockMarket ConvertMarketToInternal(UInt16 wMarket)
        {
            const int MARKET_SH = 0X4853;
            const int MARKET_SZ = 0X5A53;

            switch (wMarket)
            {
                case MARKET_SH:
                    return StockMarket.SHSE;

                case MARKET_SZ:
                    return StockMarket.SZSE;
            }

            return StockMarket.Unknown;
        }

        private string ConvertDomainClass(string domainClass)
        {
            switch (domainClass)
            {
                case "行业":
                    return "行业";

                case "概念":
                    return "概念";

                case "地域":
                    return "地区";

                //case "证监会行业":
                //    return "证监会行业";

                //case "指数板块":
                //    return "指数";
            }

            return string.Empty;
        }

        // 分析家格式财务数据
        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct DomainFileHead
        {
            public Int32 m_dwMagic1;	//	0x223FD90C;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 1)]
        struct DomainFilePack
        {
            public UInt16 m_wMarket;            // 市场类型
            [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)]
            public string m_szLabel;            // 股票代码
        }
    }
}
